home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UPatch.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  7.7 KB  |  277 lines  |  [TEXT/MPS ]

  1. //$P
  2. // UPatch.cp 
  3. // Copyright © 1985-1991 by Apple Computer, Inc.  All rights reserved. 
  4.  
  5. #include    "UPatch.h"
  6. #include    "UFailure.h"
  7. #include    "Memory.h"
  8. #include    "UMemory.h"
  9. #include    "Textedit.h"
  10. #include    "OSUtils.h"
  11. #include    "UMacAppUtilities.h"
  12.  
  13. TrapPatchPtr pPatchList = NULL;                        // global allocation declared in my header
  14.  
  15. // System heap block record for PatchTrap 
  16. typedef struct PTBlock
  17. {
  18.     short Jmp;
  19.     Ptr Routine;
  20. }    *PTBlockPtr;
  21.  
  22. // System heap block record for HeadPatch 
  23. typedef struct TPBlock
  24. {
  25.     short MoveL;
  26.     long OldTrapAddr;
  27.     short Jmp;
  28.     Ptr Routine;
  29. }    *TPBlockPtr;
  30.  
  31. // System heap block record for Head1Patch 
  32. typedef struct T1PBlock
  33. {
  34.     long MoveParameter;
  35.     short MoveL;
  36.     long OldTrapAddr;
  37.     short Jmp;
  38.     Ptr Routine;
  39. }    *T1PBlockPtr;
  40.  
  41. //--------------------------------------------------------------------------------------------------
  42. #pragma segment MAPatchRes
  43.  
  44. Ptr AllocBlock(short blockSize,
  45.                       short theTrapNum,
  46.                       TrapPatch& thePatch)
  47.  
  48. /* If blockSize is greater than zero, AllocBlock allocates a non-
  49.   relocatable block in the system heap, of size blockSize.    It then
  50.   fills all fields of thePatch.  If blockSize is zero, then no block
  51.   is allocated and AllocBlock fills fields of thePatch. */
  52.  
  53. {
  54.     Ptr theBlock;
  55.  
  56.     if (blockSize > 0)
  57.         theBlock = NewPermPtr(blockSize);
  58.     else
  59.         theBlock = NULL;
  60.  
  61.     thePatch.jmpPtr = theBlock;
  62.     thePatch.oldTrapAddr = NGetTrapAddress(theTrapNum, GetTrapType(theTrapNum));
  63.     thePatch.trapNum = theTrapNum;
  64.     thePatch.nextPatch = pPatchList;
  65.  
  66.     pPatchList = &thePatch;
  67.     return (theBlock);
  68. }
  69.  
  70. //--------------------------------------------------------------------------------------------------
  71. #pragma segment MAPatchRes
  72.  
  73. pascal short PatchTrap(TrapPatch& thePatch,
  74.                        short theTrapNum,
  75.                        Ptr theRoutine)
  76.  
  77. {
  78.     PTBlockPtr patchBlock;
  79.  
  80.     patchBlock = (PTBlockPtr)AllocBlock(0, theTrapNum, thePatch);
  81.     NSetTrapAddress((long)theRoutine, theTrapNum, GetTrapType(theTrapNum));
  82.     return (noErr);
  83. }
  84.  
  85. //--------------------------------------------------------------------------------------------------
  86. #pragma segment MAPatchRes
  87.  
  88. pascal short HeadPatch(TrapPatch& thePatch,
  89.                        short theTrapNum,
  90.                        Ptr theRoutine)
  91.  
  92. {
  93.     TPBlockPtr patchBlock;
  94.  
  95.     // Allocate the system heap block, and fill thePatch 
  96.     patchBlock = (TPBlockPtr)AllocBlock(sizeof(TPBlock), theTrapNum, thePatch);
  97.  
  98.     if (patchBlock != NULL)
  99.     {
  100.         // Stuff the code into the block 
  101.         patchBlock->MoveL = 0x2F3C;                // MOVE.L #OldTrapAddr,-(SP) 
  102.         patchBlock->OldTrapAddr = thePatch.oldTrapAddr;
  103.         patchBlock->Jmp = 0x4EF9;                // JMP #Routine 
  104.         patchBlock->Routine = theRoutine;
  105.  
  106.         // Set the trap address to the block of code in the system heap 
  107.         NSetTrapAddress((long)patchBlock, theTrapNum, GetTrapType(theTrapNum));
  108.     }
  109.     return ((short)MemError());
  110. }
  111.  
  112. //--------------------------------------------------------------------------------------------------
  113. #pragma segment MAPatchRes
  114.  
  115. pascal short Head1Patch(TrapPatch& thePatch,
  116.                         short theTrapNum,
  117.                         Ptr theRoutine)
  118.  
  119. {
  120.     T1PBlockPtr patchBlock;
  121.  
  122.     // Allocate the system heap block, and fill thePatch 
  123.     patchBlock = (T1PBlockPtr)AllocBlock(sizeof(T1PBlock), theTrapNum, thePatch);
  124.  
  125.     if (patchBlock != NULL)
  126.     {
  127.         // Stuff the code into the block 
  128.         patchBlock->MoveParameter = 0x2F2F0004;    // MOVE.L 4(SP),-(SP) 
  129.         patchBlock->MoveL = 0x2F3C;                // MOVE.L #OldTrapAddr,-(SP) 
  130.         patchBlock->OldTrapAddr = thePatch.oldTrapAddr;
  131.         patchBlock->Jmp = 0x4EF9;                // JMP #Routine 
  132.         patchBlock->Routine = theRoutine;
  133.  
  134.         // Set the trap address to the block of code in the system heap 
  135.         NSetTrapAddress((long)patchBlock, theTrapNum, GetTrapType(theTrapNum));
  136.     }
  137.     return ((short)MemError());
  138. }
  139.  
  140. //--------------------------------------------------------------------------------------------------
  141. #pragma segment MAPatchRes
  142.  
  143. TrapPatchPtr GetPreviousPatchPtr(TrapPatchPtr thePatch)
  144. // walks the patch list backwards to return the patch record just prior to (*thePatchPtr) in the patch list 
  145.  
  146. {
  147.     TrapPatchPtr tempPatchPtr = pPatchList;
  148.  
  149.     while ((tempPatchPtr != NULL) && (tempPatchPtr->nextPatch != thePatch))
  150.         tempPatchPtr = tempPatchPtr->nextPatch;
  151.     return (tempPatchPtr);
  152. }
  153.  
  154.  
  155. TrapPatchPtr GetNewerPatchPtr(TrapPatchPtr thePatch)
  156. // returns a newer patch record in the patch list which has the *same* trapNum as thePatch 
  157.  
  158. {
  159.     TrapPatchPtr aPatchPtr = GetPreviousPatchPtr(thePatch);
  160.  
  161.     while ((aPatchPtr != NULL) && (aPatchPtr->trapNum != thePatch->trapNum))
  162.         aPatchPtr = GetPreviousPatchPtr(aPatchPtr);
  163.     return (aPatchPtr);
  164. }
  165.  
  166.  
  167. pascal void UnpatchTrap(TrapPatch& thePatch)
  168.  
  169. {
  170.     /* If this trap has a newer patch than the patch we're removing, then we have to take some extra
  171.       special precautions. We have to muck with that patch's oldTrapAddr to point to this
  172.       patch record's oldTrapAddr (for both the patch record and the jumpPtr code). We can pretty well
  173.       ignore the case of an older patch on this same trap since the trapaddress in our patch record will
  174.       be correct. */
  175.     TrapPatchPtr newerPatchPtr = GetNewerPatchPtr(&thePatch);
  176.  
  177.     if (newerPatchPtr == NULL)
  178.     // only set the trap address if there *isn't* a newer patch
  179.         NSetTrapAddress(thePatch.oldTrapAddr, thePatch.trapNum, GetTrapType(thePatch.trapNum));
  180.     else
  181.     {
  182.         // set up newerPatchPtr patch record so that it points to thePatch's OldTrapAddr 
  183.         newerPatchPtr->oldTrapAddr = thePatch.oldTrapAddr;
  184.  
  185.         // set up newerPatchPtr->jmpPtr code so that it jumps to where thePatch's code jumps to 
  186.         if (newerPatchPtr->jmpPtr != NULL)
  187.         {
  188.             if (*((LongIntPtr)(newerPatchPtr->jmpPtr)) == 0x2F2F0004)// is it a Head1Patch
  189.                 ((T1PBlockPtr)newerPatchPtr->jmpPtr)->OldTrapAddr = thePatch.oldTrapAddr;
  190.             else if (*((IntegerPtr)(newerPatchPtr->jmpPtr)) == 0x2F3C)// is it a HeadPatch
  191.                 ((TPBlockPtr)newerPatchPtr->jmpPtr)->OldTrapAddr = thePatch.oldTrapAddr;
  192.             else
  193. #if qDebug
  194.                 {
  195.                 /* Writeln('###In UnpatchTrap: can''t figure out what kind of patch ',
  196.                   ORD(newerPatchPtr), ' is!'); */
  197.                 // ProgramBreak('');
  198.             }
  199. #endif
  200.  
  201.             ;
  202.         }
  203.     }
  204.  
  205.     // Unlink the patch from the linked list of patches 
  206.     if (&thePatch == pPatchList)
  207.         pPatchList = thePatch.nextPatch;
  208.     else
  209.     {
  210.         TrapPatchPtr aPatchPtr = pPatchList;
  211.  
  212.         while ((aPatchPtr != NULL) && (aPatchPtr->nextPatch != &thePatch))
  213.             aPatchPtr = aPatchPtr->nextPatch;
  214.         if (aPatchPtr != NULL)                    // Couldn't find thePatch, don't unpatch it
  215.             aPatchPtr->nextPatch = thePatch.nextPatch;
  216.     }
  217.  
  218.     // If the patch allocated a block in the system heap, deallocate it 
  219.     thePatch.jmpPtr = DisposeIfPtr(thePatch.jmpPtr);
  220. }
  221.  
  222. //--------------------------------------------------------------------------------------------------
  223. #pragma segment MAPatchRes
  224.  
  225. pascal void UnpatchAll(void)
  226.  
  227. {
  228.     while (pPatchList != NULL)
  229.         UnpatchTrap(*pPatchList);
  230. }
  231.  
  232. //--------------------------------------------------------------------------------------------------
  233. #pragma segment MAPatchRes
  234.  
  235. pascal void EachPatchDo(pascal Boolean(* DoToPatch)(TrapPatchPtr thePatchPtr,
  236.                                                     void* staticLink),
  237.                         void* staticLink)
  238.  
  239. {
  240.     TrapPatchPtr aPatchPtr = pPatchList;
  241.  
  242.     while (aPatchPtr != NULL)
  243.     {
  244.         if (!DoToPatch(aPatchPtr, staticLink))
  245.             aPatchPtr = aPatchPtr->nextPatch;
  246.         else
  247.             break;
  248.     }
  249. }
  250.  
  251. //--------------------------------------------------------------------------------------------------
  252. #pragma segment MAPatchRes
  253.  
  254. pascal void SetCallBack(ProcPtr targProc,
  255.                         long itsRefCon,
  256.                         CallBackPtr theCallBackPtr)
  257.  
  258. /*
  259.   00000000: 2F17             '/.'               MOVE.L      (A7),-(A7)    ; move old rtn address
  260.   00000002: 2F7C 1122 3344 '/|."3D'           MOVE.L      #$11223344,$0004(A7)    ; plop refcon in
  261.   0004
  262.   0000000A: 4EF9 1122 3344 'N.."3D'           JMP          0x11223344     ; shove off
  263. */
  264.  
  265. {
  266.     theCallBackPtr->saveRtnAdd = 0x2F17;
  267.     theCallBackPtr->moveRefCon = 0x2F7C;
  268.     theCallBackPtr->refCon = itsRefCon;
  269.     theCallBackPtr->targOffset = 0x0004;
  270.     theCallBackPtr->jmpInst = 0x4EF9;
  271.     theCallBackPtr->jmpTarg = (long)targProc;
  272.  
  273.     // ??? should we flush the processor cache at this point? 
  274. }
  275.  
  276.  
  277.